PureScript by Example: 関数とレコード
from PureScript by Example
ほとんど Haskell と同じなので、基本文法はガンガン飛ばす
モジュールの詳細は Persuit で確認できる
単純な型
整数: Int
浮動小数点数: Number
文字列: String
真偽値(false / true): Boolean
文字: Char
配列(すべての要素の型は同じ): Array
レコード
JavaScript のオブジェクトに相当
code:hs
author :: { name :: String, interests :: Array String }
author = { name: "Radish", interests: "Functional Programming", "Type Theory"}
フィールドには . でアクセスする: author.name
関数はインラインで記述することも可能
code:sh
:paste
… add :: Int -> Int -> Int
… add = \x y -> x + y
^D
REPL で複数行記述するには :paste を用いる
終了には ^D
独自型の定義
type キーワードを用いる
code:hs
type Entry =
{ firstName :: String
, lastName :: String
, address :: Address
}
型構築子 と カインド
List や Array は型構築子
型引数 a を受け取り、新しい型 List a(Array a)を構築する
そのため、型注釈 演算子(::)を用いて List の型を定義しようとするとエラーになる
In a type-annotated expression x :: t, the type t must have kind Type.
これはカインドに起因するエラーである
カインドとは型を区別するための概念
たとえば String や Number は Type というカインドを持つ
code:sh
:k String
Type
一方、List は Type -> Type というカインドを持つ
code:sh
:k List
Type -> Type
-> も型構築子
2 つの型引数(被演算子)と戻り値の型を取る
code:sh
:k (->)
Type -> Type -> Type
量化 された型
forall キーワードは、その型が 全称量化(すべての要素は〜, ∀)された型であることを示す
Example:
code:hs
constantlyFirst :: forall a b. a -> b -> a
constantlyFirst = \a b -> a
上記の場合、a は b の型は何でも良い
例えば、a :: Int、b :: String とした場合、constantlyFirst の型は Int -> String -> Int となる
このように具体的な型が適用されて 単相型 に変換することを 特殊化(specialized)と呼ぶ
コンパイラ が自動的に行う
η 変換(η 簡約)
η 変換 では f と \x -> f x を等価とみなす
したがって、insertEntry entry book = Cons entry book の定義は以下のように省略できる
code:hs
insertEntry entry = Cons entry -- book を削除
insertEntry = Cons -- entry も削除
これにより、関数を ポイントフリースタイル で記述することが可能となる
プロパティ取得子
\entry -> entry.address のような 無名関数 は _.address と記述できる
ネストしたプロパティを取得することも可能: _address.city
中置演算子の定義
infixr を用いると、既存の関数を 右結合 の中置演算子としてエイリアスすることができる
Example: infix 0 apply as $ -- 関数 apply を優先度 0 の右結合の中置演算子とする
中置演算子の部分適用
引数を _ と置くことで、中置演算子も部分適用することが可能
code:hs
add3 = (3 + _)
add3 1 -- 4
関数合成
PureScript の関数合成は <<< と >>> を用いる
Example:
code:hs
findEntry firstName lastName book = head (filter filterEntry book) -- 関数合成前
findEntry firstName lastName book = head <<< filter filterEntry book -- 関数合成後
これにより、η 変換が可能になる
findEntry firstName lastName = head <<< filter filterEntry
右辺は filter filterEntry >>> head と書いても良い
#読書メモ #PureScript